/*
@title: BitBoy_Platformer
@author:PenguinBoyMo
@tags: ["Platformer", "Game", "Fun"]
@addedOn: 2025-10-05
@description: Journey with BitBoy on his latest adventure
*/
// --- Sprites ---
const player = "B";
const wall = "W";
const wall2 = "R";
const background = "G";
const spike = "S";
const coin = "C";
const portal = "P";
const enemy = "E";

setLegend(
  [player, bitmap`
................
...5555555555...
...5333333335...
...5373333735...
...5373333735...
...5373333735...
...5333333335...
...5373333735...
...5337777335...
...5333333335...
...5555555555...
....5.....5.....
....5.....5.....
....555...555...
................
................`],
  [wall, bitmap`
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444`],
  [spike, bitmap`
.......33.......
.......33.......
......3333......
......3333......
.....333333.....
.....333333.....
....33333333....
....33333333....
...3333333333...
...3333333333...
..333333333333..
..333333333333..
.33333333333333.
3333333333333333
3333333333333333
3333333333333333`],
  [coin, bitmap`
................
................
.......66.......
......6666......
.....666666.....
.....666666.....
.....666666.....
......6666......
.......66.......
................
................
................
................
................
................
................`],
  [portal, bitmap`
................
....55555555....
...5555555555...
..555555555555..
.55557777775555.
.55577777777555.
.55577777777555.
.55577777777555.
.55577777777555.
.55577777777555.
.55577777777555.
.55557777775555.
..555555555555..
...5555555555...
....55555555....
................`],
  [enemy, bitmap`
................
................
.......LLL......
.......LLL......
......LLLLL.....
.....LLLLLLL....
....LLLLLLLLL...
..LLLL00000LLLL.
..LLLL02620LLLL.
..LLLL06260LLLL.
....LL02620LL...
....LL00000LL...
.....LLLLLLL....
......LLLLL.....
.......LLL......
.......LLL......`],
  [wall2, bitmap`
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDD`]
);

setSolids([player, wall, wall2]);

// --- Sounds ---
const deathSound = tune`
200: C5-200,
200: B4-200,
200: A4-200,
200: G4-200,
400: F4-400`;

const portalSound = tune`
150: C5~150,
150: E5~150,
150: G5~150,
450: C6~450`;

const coinSound = tune`
100: C5~100,
100: E5~100,
100: G5~100`;

// --- WORLD 1: Grasslands (15 levels) ---
const world1 = [
  map`
................
................
................
................
................
.........CC.....
.........WW.....
................
.......CC...CCP.
B.....C..C..WWW.
.....C..........
...CC...WWW.....
..CWW...........
..WWWW..........
.WWWWWW....E....
WWWWWWWWWWWWWWWW`,

  map`
................
.........P......
................
........WW......
................
......WW..WW....
....C...........
....WW......WW..
B.............CC
WWW...........WW
WWWW............
....W...........
CCC..W..........
CCC...W.....E...
CCC.............
WWWWWWWWWWWWWWWW`,

  map`
...C...C..C..C..
..WWWWWWWWWWWWC.
...............C
................
W...............
..............C.
...............C
..W.............
................
...............C
W.............C.
.........W......
..WW..W.....W.CC
B.WWW...........
..WWWE.....E...P
WWWWWWWWWWWWWWWW`,

  map`
................
................
................
................
................
................
.........CC.....
W..W..W..WW.....
................
................
..W.............
................
W...............
....C..CC.....P.
B...S..SSE......
WWWWWWWWWWWWWWWW`,

  map`
................
................
...............P
.............CWW
.............WW.
................
...........S....
........W.WWW...
................
......C.........
.....WW.........
...C............
..WW............
................
B......E.E..E...
WWWWWWWWWWWWWWWW`,

  map`
B...............
W...............
W...............
W.....S.........
W....WWW........
W....W..........
W..E..S..CSC...P
WWWWWWW..WWW...W
WWWWWWW..WWW..CC
WWWWWWWCC....WCC
WWWWWWWWWWWWWWWW
................
................
................
................
................`,

  map`
................
................
................
................
................
................
................
................
................
................
................
................
BSC..........CSP
WWW..........WWW
WCC...SEES...CCW
WWWWWWWWWWWWWWWW`,

  map`
................
................
................
................
................
................
..............P.
..........CSC.S.
..S.S.....WWW.W.
..WWW..........C
W.......S......C
.......WWW.....C
...............C
BW.............C
....SS.SS..SS.SC
WWWWWWWWWWWWWWWW`,

  map`
................
................
........C.......
.......WWWW.....
......W.........
.....W.....P.E..
....W......WWW..
..W.......WWWWW.
.B......WWWWWWWW
WWWW...WWWWWWWWW
WWWWW.WWWWWWWWWW
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW`,

  map`
B...............
W...............
................
................
..S.....SSC.....
.WW...SWWWW.S...
WWWWWWWWWWWWWWW.
.ECCCCCCCCCC.WW.
.WWWWWWWWWWW.WW.
................
............W...
...............W
P...C...C.......
...C.C.C.C....W.
....S...S.......
WWWWWWWWWWWWWWWW`,

  map`
................
P...............
W..SS...........
..WWWW..........
........S.S.....
.......WWWWW....
................
..............WW
.........E..S...
....E...WWWWW...
..WWWW..........
................
.W..............
B...S..S..E.S..E
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW`,

  map`
................
................
B.......C.......
................
................
..........P.....
..........W.....
.E.CCCCC..WW....
WWW......WW.WW..
WWWWS..SWWW....W
WWWWWSSWWWWEEEEE
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
................
................
................`,

  map`
................
................
................
................
................
................
...SCSCSCSCSCSCP
..WWWWWWWWWWWWWW
................
W...............
.....C.....C....
..C..W.....W.C..
..W.....W....W..
................
B....E.EE.E.E..P
WWWWWWWWWWWWWWWW`,

  map`
................
................
...............P
....SCS.........
....WWW.......W.
..SW.....S......
..WCCCCCWWW.....
.B.CCCWWWWW..W..
WWWSSWWWWWWECCCC
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
................
................
................
................
................`,

  map`
................
................
.......C........
......C.C.......
...E.C...C.P....
.WWWWW...WWWCCCC
...W......WCCCCC
..BW......WCCCCC
..WWWSSSSWWWCCCC
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
................
................
................
................
................`,

  map`
................
................
..W..W..........
.....W..........
W....W....CSC...
....WW....WWW...
.....W.CSC..SSP.
.....W.WWW..WWW.
....WW..........
..WSWWSSSSSSSSSS
BSWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
................
................
................`
];

// --- WORLD 2: Glitch Forest (15 levels, enemies added progressively)cancelded--
const world2 = [
  map`
BCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
WWWWWWWWWWWWWWWW`
];

// --- Worlds aggregate ---
const worlds = [world1, world2];

// --- Game State ---
let worldIndex = 0;
let currentLevel = 0;
let velocityY = 0;
const gravity = 0.4;
const jumpPower = -1.8;
let canJump = false;
let coins = 0;

// --- Setup map & HUD ---
setMap(worlds[worldIndex][currentLevel]);

function updateHUD() {
  clearText();
  addText(`WORLD ${worldIndex + 1}-${currentLevel + 1}`, { x: 1, y: 0, color: color`5` });
  addText(`COINS: ${coins}`, { x: 1, y: 1, color: color`6` });
}
updateHUD();

// --- Main gravity / player logic ---
setInterval(() => {
  const p = getFirst(player);
  if (!p) return;

  const below = getTile(p.x, p.y + 1);
  const onGround = below.some(t => t.type === wall);

  if (onGround) {
    velocityY = 0;
    canJump = true;
  } else {
    velocityY += gravity;
    const nextY = p.y + Math.sign(velocityY);
    const nextTile = getTile(p.x, nextY);
    if (!nextTile.some(t => t.type === wall)) p.y = nextY;
    else velocityY = 0;
  }

  const currentTile = getTile(p.x, p.y);

  // Death from spike or enemy
  if (currentTile.some(t => t.type === spike || t.type === enemy)) {
    playTune(deathSound);
    resetGame();
  }

  // Coin collect (score only)
  const coinHere = currentTile.find(t => t.type === coin);
  if (coinHere) {
    coins++;
    playTune(coinSound);
    clearTile(p.x, p.y);
    addSprite(p.x, p.y, player);
    updateHUD();
  }

  // Portal triggers next level
  if (currentTile.some(t => t.type === portal)) {
    playTune(portalSound);
    nextLevel();
  }
}, 80);

// --- Enemies: slower and back-&-forth; deadly on contact ---
const enemySpeed = 0.35;
const enemyGravity = 0.4;
setInterval(() => {
  const enemies = getAll(enemy);
  for (const e of enemies) {
    if (e._dir === undefined) e._dir = 1;
    if (e._vy === undefined) e._vy = 0;

    if (Math.random() < enemySpeed) {
      const nextTile = getTile(e.x + e._dir, e.y);
      const blocked = nextTile.some(t => t.type === wall);
      const floorAhead = getTile(e.x + e._dir, e.y + 1).some(t => t.type === wall);
      if (blocked || !floorAhead) e._dir *= -1;
      else e.x += e._dir;
    }

    // gravity for enemy
    const below = getTile(e.x, e.y + 1);
    if (!below.some(t => t.type === wall)) {
      e._vy += enemyGravity;
      const nextY = e.y + Math.sign(e._vy);
      const nextTileY = getTile(e.x, nextY);
      if (!nextTileY.some(t => t.type === wall)) e.y = nextY;
      else e._vy = 0;
    } else {
      e._vy = 0;
    }

    // kill player on contact
    if (getTile(e.x, e.y).some(t => t.type === player)) {
      playTune(deathSound);
      resetGame();
    }
  }
}, 180);

// --- Controls ---
onInput("a", () => {
  const p = getFirst(player);
  if (p && !getTile(p.x - 1, p.y).some(t => t.type === wall)) p.x -= 1;
});
onInput("d", () => {
  const p = getFirst(player);
  if (p && !getTile(p.x + 1, p.y).some(t => t.type === wall)) p.x += 1;
});
onInput("w", () => {
  const p = getFirst(player);
  if (!p || !canJump) return;
  velocityY = jumpPower;
  p.y -= 1;
  canJump = false;
});

// --- Helpers ---
function resetGame() {
  const p = getFirst(player);
  if (p) {
    p.x = 1;
    p.y = 8;
  }
  updateHUD();
}

function nextLevel() {
  currentLevel++;
  if (currentLevel >= worlds[worldIndex].length) {
    worldIndex++;
    currentLevel = 0;
    if (worldIndex >= worlds.length) {
      clearText();
      addText("GAME COMPLETE!", { x: 4, y: 6, color: color`5` });
      addText(`COINS: ${coins}`, { x: 6, y: 8, color: color`6` });
      return;
    }
  }
  setMap(worlds[worldIndex][currentLevel]);
  resetGame();
  updateHUD();
}
